package cn.layfolk.daimao.config;

import cn.layfolk.daimao.config.properties.SecurityProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;

import java.util.List;
import java.util.Map;


/**
 * 资源服务器配置
 */
@Configuration
@EnableResourceServer
public class ResouceServerConfig extends
        ResourceServerConfigurerAdapter {

    @Autowired
    private SecurityProperty securityProperty;

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private AuthExceptionEntryPoint authExceptionEntryPoint;
    @Autowired
    private CustomAccessDeniedHandler customAccessDeniedHandler;

    @Value("${spring.application.name}")
    private String applicationName;


    //public static final String RESOURCE_ID = "res1";


    //资源服务令牌解析服务
    // 如果资源服务器和授权服务器在一个应用内，直接使用  DefaultTokenServices就好，分离的用远程服务校验token
//    @Bean
//    public ResourceServerTokenServices tokenService() {
//        //使用远程服务请求授权服务器校验token,必须指定校验token 的url、client_id，client_secret
//        RemoteTokenServices service = new RemoteTokenServices();
//        service.setCheckTokenEndpointUrl("http://localhost:8888/oauth/check_token");
//        service.setClientId("c1");
//        service.setClientSecret("secret");
//        return service;
//    }





    /**
     * 这里配置好后会自动调用JwtAccessTokenConverter将jwt解析出来
     * @param resources
     * @throws Exception
     */
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {

        String resourceId = securityProperty.getResourceId();
        if (resourceId == null) {
            resourceId = applicationName;
        }

        resources.resourceId(resourceId)  //资源服务id
                //.tokenServices(tokenService()) //实现令牌服务,用jwt模式，就不用每次远程调用授权服务验证了
                .tokenStore(tokenStore)
                .stateless(true)
                .authenticationEntryPoint(authExceptionEntryPoint)
                .accessDeniedHandler(customAccessDeniedHandler);
    }



    /**
     * 配置资源的拦截规则
     * @param http
     * @throws Exception
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.cors();
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/login").permitAll()
                .antMatchers("/account/clientLogin").permitAll()
                .antMatchers("/account/clientLogout").permitAll()
                .antMatchers("/actuator/**").permitAll()
                .antMatchers("/anonymous/**").permitAll()
                .antMatchers("/doc.html/**").permitAll()
                .antMatchers("/webjars/**").permitAll()
                .antMatchers("/swagger/**").permitAll()
                .antMatchers("/swagger-resources/**").permitAll()
                .antMatchers("/v2/**").permitAll()
              ;
                //.antMatchers("/**").access("#oauth2.hasScope('all')")
                //.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        // 添加角色和权限关系
        addUrlAndRole(http);

        // 添加放行路径
        List<String> permitList = securityProperty.getPermitAll();
        if (permitList != null) {
            permitList.forEach(e -> {
                try {
                    http.authorizeRequests().antMatchers(e).permitAll();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            });
        }
        http.authorizeRequests().anyRequest().authenticated();
    }

    /**
     * 添加角色和权限关系
     */
    private void addUrlAndRole(HttpSecurity http) {
        Map<String, List<String>> map = securityProperty.getUrlAndRole();
        if (map != null) {
            map.forEach((url,roles) -> {
                String[] params = new String[15];
                for (int i = 0; i < roles.size(); i++) {
                    params[i] = roles.get(i);
                }
                try {
                    http.authorizeRequests().antMatchers(url).hasAnyAuthority(params);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
    }


}
